package com.swotxu.oldwebproject.session.utils;

import com.swotxu.oldwebproject.redis.RedisManager;
import com.swotxu.oldwebproject.redis.connection.IRedisConnection;
import com.swotxu.oldwebproject.redis.utils.RedisPropertiesUtil;
import com.swotxu.oldwebproject.session.RedisSession;
import com.swotxu.oldwebproject.session.RedisSessionRepository;
import com.swotxu.oldwebproject.utils.SessionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * 类比 ServletContext
 * 面向 redis，记录全局用户登录信息
 *
 * 获取当日在线人数，只需获取 key: KEY_SID_TO_USER 下的 sessionidMap集合即可 (Map<sessionid, userid+username>)
 * 获取当日登录过的用户数，只需获取 key: KEY_USER_TO_LOGINNUM 下的 useridMap集合即可 (Map<userid+username, loginNum>)
 *
 * @Date: 2020/1/16 17:42
 * @Author: xu.hai
 */
public class RedisServletContext {
    private static final Logger LOGGER = LoggerFactory.getLogger(RedisServletContext.class);

    private static IRedisConnection redisConnection = RedisManager.getIRedisConnection();
    private static RedisSessionRepository repository = new RedisSessionRepository(redisConnection);

    /*private final static String KEY_SID_TO_USER = RedisSessionUtil.SERVLETCONTEXT + "sessionIdToUser";
    private final static String KEY_ATTR_SID_TO_USER = "sessionIdAttr:";
    private final static String KEY_USER_TO_LOGINNUM = RedisSessionUtil.SERVLETCONTEXT + "userToLoginNum";
    private final static String KEY_ATTR_USER_TO_LOGINNUM = "userAttr:";*/

    /**
     * 获取当前有效在线 session 集
     *
     * @return
     */
    public static List<HttpSession> getConcurrentVaildSession(){
        Set<String> sessionids;
        if(!RedisPropertiesUtil.isEnable() || (sessionids = redisConnection.keys(RedisSessionUtil.SESSION_PREFIX)) == null){
            LOGGER.warn("Redis not available or No login user！");
            return Collections.unmodifiableList(Collections.EMPTY_LIST);
        }
        List<HttpSession> onLineSessions = new ArrayList();
        for (String sessionid : sessionids) {
            String token = sessionid.substring(RedisSessionUtil.SESSION_PREFIX.length());
            HttpSession session = RedisSession.createExistSession(token, null, redisConnection);
            if(session != null && session.getAttribute(SessionUtil.KEY_USERINFO) != null){
                onLineSessions.add(session);
            }
        }
        return Collections.unmodifiableList(onLineSessions);
    }

    /*private static String getUserIdAndNameKey(String userId, String username){
        return String.format("%s,%s", userId, username);
    }

    *//**
     * 获取当日登陆过的用户集
     *
     * @return 数据结构 List<Pair<userid+","+username, loginNum>>
     *//*
    public static List<Pair<String, Integer>> getLoggedToday(){
        Set<String> userkeys;
        if(!RedisPropertiesUtil.isCanUsingRedis() || (userkeys = redisConnection.hkeys(KEY_USER_TO_LOGINNUM)) == null){
            logger.warn("Redis not available or No login user！");
            return Collections.unmodifiableList(Collections.EMPTY_LIST);
        }
        List<Pair<String, Integer>> loggedToday = new ArrayList();
        for (String userkey : userkeys) {
//            String loginNum = (String) redisConnection.hget(KEY_USER_TO_LOGINNUM, userkey);
            int loginNum = getLoginNumByAttrUser(userkey);
            loggedToday.add(new Pair(userkey, loginNum));
        }
        return Collections.unmodifiableList(loggedToday);
    }

    *//**
     * 获取今日，当前在线用户人数集
     *
     * @return 数据结构 List<Pair<sessionid, userid+","+username>>
     *//*
    public static List<Pair<String, String>> getOnlineToday(){
        Set<String> sessionids;
        if(!RedisPropertiesUtil.isCanUsingRedis() || (sessionids = redisConnection.hkeys(KEY_SID_TO_USER)) == null){
            logger.warn("Redis not available or No login user！");
            return Collections.unmodifiableList(Collections.EMPTY_LIST);
        }
        List<Pair<String, String>> onlineUsers = new ArrayList();
        for (String sessionid : sessionids) {
            String userIdAndUserName = (String) redisConnection.hget(KEY_SID_TO_USER, sessionid);
            onlineUsers.add(new Pair(sessionid, userIdAndUserName));
        }
        return Collections.unmodifiableList(onlineUsers);
    }

    *//**
     * 用户登录时，记录当前用户登录次数
     *      -- 避免同一用户多次登录，导致的下线统计问题
     *
     * @param sessionId
     * @param userId
     *//*
    public static void loginAndRecord(String sessionId, String userId, String username){
        if(!RedisPropertiesUtil.isCanUsingRedis()){
            logger.warn("Redis not available！");
            return;
        }
        String userkey = getUserIdAndNameKey(userId, username);
        // 缓存 sessionid 与 userid 对应关系
        setUserBySessionId(sessionId, userkey);

        // 先检查当前用户是否已登录过，并记录用户登录次数
        int num = getLoginNumByUser(userkey);
        setLoginNumByUser(userkey, ++ num);
        logger.info(String.format("---------用户登录------- sessionId: %s, 用户: %s, 当前登录次数: %d", sessionId, userkey, num));
    }

    *//**
     * 用户退出时，更新用户登录次数，标记用户下线
     *
     * @param sessionId
     *//*
    public static void logoutAndRecord(String sessionId){
        if(!RedisPropertiesUtil.isCanUsingRedis()){
            logger.info("Redis not available！");
            return;
        }
        // 获得当前用户登录次数
        String userkey = getUserBySessionId(sessionId);
        if(StringUtils.isBlank(userkey)){
            logger.info("userId not found according to sessionid!");
            return;
        }
        int num = getLoginNumByUser(userkey);
        logger.info(String.format("---------用户退出------- sessionId: %s, 用户: %s, 当前登录次数: %d", sessionId, userkey, num));

        // 登录次数减 1，并回写redis（这里保留 num=0 的用户信息，可用户统计当日登录过的用户总数）
        setLoginNumByUser(userkey, --num);

        // 用户完全下线，更新DB
        String[] userinfo = userkey.split(",");
        Date logoutDate = new Date();
        if(num <= 0){
            Sql sql = new Sql("UPDATE G_USERINFO SET ISONLINE=0,LASTACTIVETIME = ? WHERE ID = ?");
            sql.getParameters().add("LASTACTIVETIME", logoutDate, DbType.DATE);
            sql.getParameters().add("ID", userinfo[0], DbType.NUMERIC);
            DBManager.execute(sql);
        }
        // 删除 sessionid 缓存
        delUserBySessionId(sessionId);

        // --------------------------------------------------------- 记录日志
        String formName = userinfo[1] + " 登出了系统";
        Log log = new Log(formName);// 操作内容
        log.setAction(100005002);// 操作类型
        log.setBody(formName);// 操作内容
        log.setUserID(Long.valueOf(userinfo[0]));// 操作用户ID
        log.setDate(logoutDate);// 操作时间
        log.setClasz(655299);// 表单模块ID
        xsf.platform.Logger.info(log); // 保存进g_log表
        // ---------------------------------------------------------
    }

    *//**
     * 尝试清除 redis 中全局用户信息相关缓存
     * 在多台服务器集群下，某一台服务器无法直接清空全局信息，否则会导致其他服务器的用户信息丢失
     * 清除先需检查：
     * 1、检查是否开启使用 Redis Session
     * 2、检查 redis是否可用
     * 3、检查当前是否为最后一台存活服务器
     * @return
     *//*
    public static boolean tryRemoveAll(){
        if(RedisSessionHelper.isUseRedisSession() && RedisPropertiesUtil.isCanUsingRedis() && RedisSessionUtil.checkOnlineServer()){
            logger.info("Redis ServletContext -> try removeAll success!");
            // 清空 session 数据
            RedisSessionUtil.delAllByRegexKey(RedisSessionUtil.SESSION + "*");
            // 清空 servletContext 数据
            RedisSessionUtil.delAllByRegexKey(RedisSessionUtil.SERVLETCONTEXT + "*");

//            redisConnection.del(KEY_SID_TO_USER);
//            redisConnection.del(KEY_USER_TO_LOGINNUM);
            return true;
        }else {
            logger.info("Redis ServletContext -> try removeAll failed!");
            return false;
        }
    }

    *//**
     * 设置 sessionid -> useridAndUsername 映射
     * @param sessionId
     * @param userKey
     *//*
    public static void setUserBySessionId(String sessionId, String userKey){
        redisConnection.hset(KEY_SID_TO_USER, KEY_ATTR_SID_TO_USER + sessionId, userKey);
    }
    *//**
     * 根据 sessionid 获取 useridAndUsername
     * @param sessionId
     * @return
     *//*
    public static String getUserBySessionId(String sessionId){
        Object hget = redisConnection.hget(KEY_SID_TO_USER, KEY_ATTR_SID_TO_USER + sessionId);
        return hget == null? "" : String.valueOf(hget);
    }

    *//**
     * 删除 sessionid  -> useridAndUsername 映射
     * @param sessionId
     * @return
     *//*
    public static long delUserBySessionId(String sessionId){
        return redisConnection.hdel(KEY_SID_TO_USER, KEY_ATTR_SID_TO_USER + sessionId);
    }
    *//**
     * 设置 useridAndUsername -> logNum 映射
     * @param userKey
     * @param logNum
     *//*
    public static void setLoginNumByUser(String userKey, int logNum){
        redisConnection.hset(KEY_USER_TO_LOGINNUM, KEY_ATTR_USER_TO_LOGINNUM + userKey, logNum);
    }
    *//**
     * 根据 useridAndUsername 获取 登录数
     * @param userKey
     * @return
     *//*
    public static int getLoginNumByUser(String userKey){
        return getLoginNumByAttrUser(KEY_ATTR_USER_TO_LOGINNUM + userKey);
    }
    public static int getLoginNumByAttrUser(String attrUserKey){
        Integer logNum = 0;
        Object numObj = redisConnection.hget(KEY_USER_TO_LOGINNUM, attrUserKey);
        if(numObj != null){
            logNum = Integer.valueOf(numObj.toString());
        }
        return logNum;
    }

    *//**
     * 删除 useridAndUsername -> logNum 映射
     * @param userKey
     * @return
     *//*
    public static long delLoginNumByUser(String userKey){
        return redisConnection.hdel(KEY_USER_TO_LOGINNUM, KEY_ATTR_USER_TO_LOGINNUM + userKey);
    }*/
    public static void logoutAndRecord(String sessionId){}
}
